package com.aleyn.router.core

import android.os.Bundle

/**
 * @author: Aleyn
 * @date: 2023/7/17 16:20
 *
 * 路由 URL 解析类。
 * 用于解析形如 "/path/to/page?key1=value1&key2=value2" 的路由字符串，
 * 将其分解为路由主键 (routerKey) 和查询参数。
 *
 * @param routerKey 路由主键，即 URL 中 '?' 之前的部分。
 * @param queryNamesAndValues 查询参数列表，格式为 [key1, value1, key2, value2, ...]。
 * @param url 完整的原始 URL 字符串。
 */
class RouterUrl internal constructor(
    internal val routerKey: String,
    private val queryNamesAndValues: List<String?>?,
    private val url: String
) {
    /**
     * 将所有查询参数转换为 Bundle。
     * @return 包含所有查询参数的 Bundle，如果没有参数则返回 null。
     */
    fun queryAllParameter(): Bundle? {
        if (queryNamesAndValues == null) return null
        val bundle = Bundle()
        for (i in queryNamesAndValues.indices step 2) {
            bundle.putString(queryNamesAndValues[i], queryNamesAndValues[i + 1])
        }
        return bundle
    }

    override fun equals(other: Any?): Boolean {
        return other is RouterUrl && other.url == url
    }

    override fun hashCode(): Int = url.hashCode()

    override fun toString(): String = url


    companion object {

        /**
         * 解析输入的 URL 字符串，创建 RouterUrl 实例。
         */
        private fun parse(input: String): RouterUrl {
            // 移除首尾的 ASCII 空白字符
            val start = input.indexOfFirstNonAsciiWhitespace()
            val limit = input.indexOfLastNonAsciiWhitespace(start)

            // 查找查询参数分隔符 '?'
            val pos = input.indexOfFirst { it == '?' }
            return if (pos > -1 && pos < limit) {
                val routerKey = input.substring(start, pos)
                val param = input.substring(pos + 1)
                RouterUrl(routerKey, param.toQueryNamesAndValues(), input)
            } else {
                RouterUrl(input, null, input)
            }
        }

        /**
         * 将查询参数字符串 (key1=value1&key2=value2) 解析为键值对列表。
         */
        private fun String.toQueryNamesAndValues(): MutableList<String?> {
            val result = mutableListOf<String?>()
            var pos = 0
            while (pos <= length) {
                var ampersandOffset = indexOf('&', pos)
                if (ampersandOffset == -1) ampersandOffset = length

                val equalsOffset = indexOf('=', pos)
                if (equalsOffset == -1 || equalsOffset > ampersandOffset) {
                    // 只有键，没有值
                    result.add(substring(pos, ampersandOffset))
                    result.add(null) // No value for this name.
                } else {
                    // 同时有键和值
                    result.add(substring(pos, equalsOffset))
                    result.add(substring(equalsOffset + 1, ampersandOffset))
                }
                pos = ampersandOffset + 1
            }
            return result
        }

        /**
         * String 的扩展方法，用于将字符串转换为 RouterUrl 对象。
         */
        internal fun String.toRouterUrl() = parse(this)
    }

}

/**
 * 查找字符串中第一个非 ASCII 空白字符的索引。
 */
fun String.indexOfFirstNonAsciiWhitespace(startIndex: Int = 0, endIndex: Int = length): Int {
    for (i in startIndex until endIndex) {
        when (this[i]) {
            '\t', '\n', '\u000C', '\r', ' ' -> Unit
            else -> return i
        }
    }
    return endIndex
}

/**
 * 查找字符串中最后一个非 ASCII 空白字符的索引。
 */
fun String.indexOfLastNonAsciiWhitespace(startIndex: Int = 0, endIndex: Int = length): Int {
    for (i in endIndex - 1 downTo startIndex) {
        when (this[i]) {
            '\t', '\n', '\u000C', '\r', ' ' -> Unit
            else -> return i + 1
        }
    }
    return startIndex
}

/**
 * 从完整的 URL 字符串中提取路由主键 (routerKey)。
 */
internal fun String.getRouterKey(): String {
    val start = this.indexOfFirstNonAsciiWhitespace()
    val limit = this.indexOfLastNonAsciiWhitespace(start)
    val pos = this.indexOfFirst { it == '?' }
    return if (pos > -1 && pos < limit) this.substring(start, pos) else this
}